import { sys } from 'cc'
import { aes_decrypt, aes_encrypt, md5 } from '../encrypt/Cryptor';
import { lwarn } from '../logger/Logger';

export default class LocalData {
    private static _key: string | null = null;
    private static _iv: string | null = null;
    private static _enableCryptor: boolean = false;

    /**
     * 初始化本地数据存储器
     * @param enable 是否加密
     * @param key 加密时所用的key
     * @param iv 加密时所有的iv
     */
    public static Init(enable: boolean, key: string = null, iv: string = null) {
        this.EnableCryptor(enable);
        this._key = key;
        this._iv = iv;
    }

    public static EnableCryptor(enable: boolean) {
        this._enableCryptor = enable;
    }

    public static Set(key: string, value: any) {
        if (key == null) {
            lwarn("local data's key is null");
            return;
        }

        if (value == null) {
            this.Remove(key);
            return;
        }

        const valType: string = typeof value;
        if (valType === "object") {
            value = JSON.stringify(value);
        }

        sys.localStorage.setItem(this._GetKey(key), this._Encrypt(value.toString()));
    }

    public static Get(key: string, defaultVal: any = null): any {
        let value = sys.localStorage.getItem(this._GetKey(key));
        if (value == null) {
            return defaultVal;
        }

        return this._Decrypt(value);
    }

    public static GetNumber(key: string, defaultVal: number = 0): number {
        let value = this.Get(key);
        if (value == null) {
            return defaultVal;
        }

        return Number(value);
    }

    public static GetBoolean(key: string, defaultVal: boolean = false) {
        let value = this.Get(key);
        if (value == null) {
            return defaultVal;
        }

        return Boolean(value);
    }

    public static GetObj(key: string, defaultVal: object = null) {
        let value = this.Get(key);
        if (value === null) {
            return defaultVal;
        }

        return JSON.parse(value);
    }

    public static Remove(key: string) {
        if (key == null) {
            lwarn("local data's key is null")
            return;
        }

        sys.localStorage.removeItem(this._GetKey(key));
    }

    public static Clear() {
        sys.localStorage.clear();
    }

    private static _GetKey(key: string) {
        return md5(key);
    }

    private static _Encrypt(data: string) {
        return this._enableCryptor ? aes_encrypt(data, this._key, this._iv) : data;
    }

    private static _Decrypt(data: string) {
        return this._enableCryptor ? aes_decrypt(data, this._key, this._iv) : data;
    }
}

export function local_set(key: string, value: any) {
    LocalData.Set(key, value);
}

export function local_get(key: string, defaultVal: any = null) {
    return LocalData.Get(key, defaultVal);
}

export function local_num(key: string, defaultVal: number = 0) {
    return LocalData.GetNumber(key, defaultVal);
}

export function local_bool(key: string, defaultVal: boolean = false) {
    return LocalData.GetBoolean(key, defaultVal);
}

export function local_obj(key: string, defaultVal: object = null) {
    return LocalData.GetObj(key, defaultVal);
}

export function local_remove(key: string) {
    LocalData.Remove(key);
}

export function local_clear() {
    LocalData.Clear();
}